命名参数

  使用可选参数时,可能发现某个方法有几个可选参数,但你可能只想给第三个可选参数传送值。从上一节介绍的语法来看,如果不提供前两个可选参数的值,就无法给第三个可选参数传送值。

  C# 4引入了命令参数(named parameters),它允许指定要使用哪个参数。这不需要在方法定义中进行任何特殊处理,它是一个在调用方法时使用的技术。其语法如下:

    MyMethod(
        <param1Name> : <param1Value>,
        ...
        <paramNName> : <paramNValue>);

  参数的名称是在方法定义中使用的变量名。

  只要命名参数存在,就可以采用这种方式指定需要的任意多个参数,而且参数的顺序是任意的。命名参数也可以是可选的。

  可以仅给方法调用中的某些参数使用命名参数。当方法签名中有多个可选参数和一些必选参数时,这是非常有用的。可以首先指定必选参数,再指定命名的可选参数。例如:

    MyMethod(
        requiredParameter1Value,
        optionalParameter5 : optionalParameter5Value);

  但注意,如果混合使用命名参数和位置参数,就必须先包含所有的位置参数,其后是命名参数。但是,只要全部使用命名参数,参数的顺序也可以不同。例如:

    MyMethod(
        optionalParameter5 : optionalParameter5Value,
        requiredParameter1 : requiredParameter1Value);

  此时,必须包含所有必选参数的值。

  下面的示例介绍了如何使用命名参数和可选参数。

    public static class WordProcessor
    {
        public static List<string> GetWords (
            string sentence,
            bool capitalizeWords = false,
            bool reverseOrder = false,
            bool reverseWords = false)
        {
            List<string> words = new List<string>(sentence.Split(' '));
            if(capitalizeWords)
                words = CapitalizeWords(words);
            if(reverseOrder)
                words = ReverseOrder(words);
            if(reverseWords)
                words = ReverseWords(words);
            return words;
        }

        private static List<string> CapitalizeWords(
            List<string> words)
        {
            List<string> capitalizedWords = new List<string>();
            foreach(string word in words)
            {
                if(word.Length == 0)
                    continue;
                if(word.Length == 1)
                    capitalizedWords.Add(
                        word[0].ToString().ToUpper());
                else
                    capitalizedWords.Add(
                        word[0].ToString().ToUpper()
                        + word.Substring(1));
            }
        }

        private static List<string> ReverseOrder(List<string words>)
        {
            List<string> reversedWords = new List<string>();
            for(int wordIndex = words.Count - 1;
                wordInde >= 0; wordIndex--)
                reversedWords.Add(words[wordIndex]);

            return reversedWords;
        }

        private static List<string> ReverseWords(List<string> words)
        {
            List<string> reversedWords = new List<string>();
            foreach(string word in words)
                reversedWords.Add(ReverseWord(word));

            return reversedWords;
        }

        private static string ReverseWord(string work)
        {
            StringBuilder sb = new StringBuilder();
            for(int characterIndex = word.Length - 1;
                characterIndex >= 0; characterIndex--)
                sb.Append(word[characterIndex]);

            return sb.ToString();
        }

        static void Main(string[] args)
        {
            string sentence = "'twas brillig, and the slithy toves did gyre "
                + "and gimble in the wabe:";
            List<string> words;

            words = WordProcessor.GetWords(sentence:);
            foreach(string word in words)
            {
                Console.Write(word);
                Console.Write(' ');
            }

            Console.WriteLine('\n');

            words = WordProcessor.GetWords(
                sentence,
                reverseWords : true,
                capitalizeWords : true);
            Console.WriteLine("Capitalized sentence with reversed words:");
            foreach(string word in words)
            {
                Console.Write(word);
                Console.Write(' ');
            }

            Console.ReadKey();
        }
    }

  示例的说明

  这个示例创建了一个执行一些简单的字符串处理的实用类,再使用这个类修改一个字符串。类中的单个公共方法包含一个必选参数和3个可选参数:

    public static List<string> GetWords (
        string sentence,
        bool capitalizeWords = false,
        bool reverseOrder = false,
        bool reverseWords = false)
    {
        ...
    }

  这个方法返回string值的一个集合,每个string值都是初始输入的一个单词。根据指定的可选参数,可能会进行额外的转换: 对字符串集合进行整体转换,或者仅转换某个单词。

  这里并未深入探讨WordProcessor类的功能,读者可以自己研究它的代码,考虑一下如何改进这些代码,例如\'twas应该为\'Twas吗?如何进行这个修改?

  调用这个方法时,只使用了两个可选参数,第三个参数(reverseOrder)使用其默认值false:

    words = WordProcessor.GetWords(
        sentence,
        reverseWords : true,
        capitalizeWords  true);

  还要注意,所指定的两个参数的顺序与定义它们的顺序不同。

  最后要注意的是,处理带有可选参数的方法时,使用IntelliSense会非常方便。输入这个示例的代码时,注意GetWords()方法的工具提示,如图14-10所示(把鼠标指针停放在方法调用上,也会看到这个工具提示)。

  这是一个非常有用的工具提示,它不仅显示了可用参数的名称,还显示了可选参数的默认值,非常便于确定是否需要重写某个默认值。

🔚